package msjcalendar;
import java.util.EnumSet;
import java.util.GregorianCalendar;


import org.w3c.dom.Element;

import enums.DayEnum;

import utility.XmlHelper;



/**
 * @author Sebastian, Markus
 *
 */
public class WeeklyPattern extends Pattern {
	
	/**
	 * repeating days.
	 */
	private EnumSet<DayEnum> weekDay;
	
	/**
	 * @return creates a xml-representation of the weekday enumset
	 */
	private Element weekDayToXml() {
		Element result = XmlHelper.getXmlDoc().createElement("weekDay");
		String s = "";
		for (DayEnum e: weekDay) {
			s = s.concat(String.valueOf(e.getValue()));
		}
		result.appendChild(XmlHelper.getXmlDoc().createTextNode(s));
		return result;
	}
	
	
	/**
	 * @param xmlElement XML-Element the WeeklyPattern is constructed from
	 */
	public WeeklyPattern(final Element xmlElement) {
		super(xmlElement);
		this.weekDay = EnumSet.noneOf(enums.DayEnum.class);
		String wd = utility.XmlHelper.getFirstChildWithTagName(xmlElement, "weekDay").getTextContent();
		for (int i = 0; i < wd.length(); ++i) {
			int day = Integer.parseInt(wd.substring(i, i + 1));
			this.weekDay.add(enums.DayEnum.values()[day - 1]);
		}
	}
	/**
	 * @param weekDay Wochentage
	 * @param duration Dauer
	 * @param frequency Haeufigkeit
	 */
	public WeeklyPattern(final EnumSet<DayEnum> weekDay, final int duration, final int frequency) {
		super(duration, frequency);
		this.weekDay = weekDay;
	}
	
	/**
	 * @return Wochentage
	 */
	public EnumSet<DayEnum> getWeekDay() {
		return weekDay;
	}
	
	/**
	 * @param value Wert
	 */
	public void setWeekDay(final EnumSet<DayEnum> value) {
		this.weekDay = value;
	}

	@Override
	public boolean isMatching(final GregorianCalendar begin, final GregorianCalendar end,
			final GregorianCalendar dateToMatch) {
		int yearDiff = dateToMatch.get(GregorianCalendar.YEAR) - begin.get(GregorianCalendar.YEAR);
		int weekDiff = dateToMatch.get(GregorianCalendar.WEEK_OF_YEAR) - begin.get(GregorianCalendar.WEEK_OF_YEAR);
		boolean isLater;
		if (yearDiff > 0) {
			weekDiff += 52 - begin.get(GregorianCalendar.WEEK_OF_YEAR);
			weekDiff += (yearDiff - 1) * 52;
			isLater = true;
		} else if (yearDiff == 0) {
			isLater = weekDiff >= 0; 
		} else {
			isLater = false; 
		}
		
		int dayOfWeek = dateToMatch.get(GregorianCalendar.DAY_OF_WEEK);
		if (dayOfWeek == 1) {
			dayOfWeek = 8;
		}
		return (this.getWeekDay().contains(
				DayEnum.values()[dayOfWeek - 2])
				&& (weekDiff % this.getFrequency() == 0)
				&& isLater
				&& ((this.getDuration() == 0) || (weekDiff <= this.getDuration())));
	}

	@Override
	public Element toXml() {
		Element result = XmlHelper.getXmlDoc().createElement("eventPattern");
		result.setAttribute("type", "weekly");
		result.appendChild(XmlHelper.createTextElement("duration", String.valueOf(this.getDuration())));
		result.appendChild(XmlHelper.createTextElement("frequency", String.valueOf(this.getFrequency())));
		result.appendChild(this.weekDayToXml());
		return result;
	}
}